﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using HouseOfCards;
using System.Threading;
using System.Diagnostics;
using System.IO;

using log4net;
using log4net.Config;

namespace VideoPoker
{

   public partial class Form1 : Form
   {
      private static readonly ILog _logger = LogManager.GetLogger("videopoker");

      private Game _game;
      private Deck _deck;
      private Hand _hand;
      private bool _cell1;
      private bool _cell2;
      private bool _cell3;
      private bool _cell4;
      private bool _cell5;

      private bool _hold1;
      private bool _hold2;
      private bool _hold3;
      private bool _hold4;
      private bool _hold5;

      public Form1()
      {
         InitializeComponent();

         //start the logger
         string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
         string log4netFile = path + "\\log4net.config";
         FileInfo configFile = new FileInfo(log4netFile);
         log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);

         _logger.Info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
         _logger.Info("Starting Video Poker - Ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion);

         _deck = new Deck();
         _deck.Shuffle();

         _game = new Game();
         _game.Credits = 80;
         _game.GameType = GameTypes.DoubleBonus;

         _hand = new Hand(_game.GameType);
         _hand.DealCount = 0;
         _hand.CoinValue = .25M;
         _hand.CoinsPlayed = 5;

         lblHold1.Visible = false;
         lblHold2.Visible = false;
         lblHold3.Visible = false;
         lblHold4.Visible = false;
         lblHold5.Visible = false;

         this.lblCredits.Text = _game.Credits.ToString();

         dgPayTable.BorderStyle = BorderStyle.None;
         DisplayPayTable();
      }

      private void DisplayPayTable()
      {
         dgPayTable.AutoGenerateColumns = false;

         DataGridViewTextBoxColumn handColumn = new DataGridViewTextBoxColumn();
         handColumn.DataPropertyName = "Hand";
         handColumn.HeaderText = "Hand";

         DataGridViewTextBoxColumn credit1Column = new DataGridViewTextBoxColumn();
         credit1Column.DataPropertyName = "Credit1";
         credit1Column.HeaderText = "1 Credit";

         DataGridViewTextBoxColumn credit2Column = new DataGridViewTextBoxColumn();
         credit2Column.DataPropertyName = "Credit2";
         credit2Column.HeaderText = "2 Credit";

         DataGridViewTextBoxColumn credit3Column = new DataGridViewTextBoxColumn();
         credit3Column.DataPropertyName = "Credit3";
         credit3Column.HeaderText = "3 Credit";

         DataGridViewTextBoxColumn credit4Column = new DataGridViewTextBoxColumn();
         credit4Column.DataPropertyName = "Credit4";
         credit4Column.HeaderText = "4 Credit";

         DataGridViewTextBoxColumn credit5Column = new DataGridViewTextBoxColumn();
         credit5Column.DataPropertyName = "Credit5";
         credit5Column.HeaderText = "5 Credit";

         dgPayTable.Columns.Add(handColumn);
         dgPayTable.Columns.Add(credit1Column);
         dgPayTable.Columns.Add(credit2Column);
         dgPayTable.Columns.Add(credit3Column);
         dgPayTable.Columns.Add(credit4Column);
         dgPayTable.Columns.Add(credit5Column);

         dgPayTable.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[0].FillWeight = 33;

         dgPayTable.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[1].FillWeight = 13;
         dgPayTable.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[2].FillWeight = 13;
         dgPayTable.Columns[3].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[3].FillWeight = 13;
         dgPayTable.Columns[4].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[4].FillWeight = 13;
         dgPayTable.Columns[5].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
         dgPayTable.Columns[5].FillWeight = 13;


         PayLines pl = new PayLines();
         BindingList<PayLine> payLines = pl.GetPayLines(GameTypes.DoubleBonus);

         dgPayTable.DataSource = payLines;

         BindingManagerBase bmb = this.BindingContext[dgPayTable.DataSource, dgPayTable.DataMember];
         int n = bmb.Count;
         bmb.Position = n - 1; // move the triangle to the last item
      }

      private void btnDeal_Click(object sender, EventArgs e)
      {
         Card card;
         PayOut po;

         if (_hand.DealCount == 0)
         {
            _hold1 = false;
            _hold2 = false;
            _hold3 = false;
            _hold4 = false;
            _hold5 = false;

            _deck.Shuffle();
            _hand.Clear();
            _cell1 = false;
            _cell2 = false;
            _cell3 = false;
            _cell4 = false;
            _cell5 = false;
            _game.Credits -= _hand.CoinsPlayed;
            lblCredits.Text = _game.Credits.ToString();
            lblGameStatus.Text = "";


            //deal a new hand
            for (int i = 0; i < 5; i++)
            {
               card = _deck.GetNextCard();
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               if (!_cell1)
               {
                  this.cardImage1.CardValue = card.Value;
                  _cell1 = true;
                  _hand.Card1 = new Card(card.Value);
               }
               else if (!_cell2)
               {
                  this.cardImage2.CardValue = card.Value;
                  _cell2 = true;
                  _hand.Card2 = new Card(card.Value);
               }
               else if (!_cell3)
               {
                  this.cardImage3.CardValue = card.Value;
                  _cell3 = true;
                  _hand.Card3 = new Card(card.Value);
               }
               else if (!_cell4)
               {
                  this.cardImage4.CardValue = card.Value;
                  _cell4 = true;
                  _hand.Card4 = new Card(card.Value);
               }
               else if (!_cell5)
               {
                  this.cardImage5.CardValue = card.Value;
                  _cell5 = true;
                  _hand.Card5 = new Card(card.Value);
               }
               this.Refresh();
               Thread.Sleep(250);
            }

            DumpCards();
            po = _hand.Evaluate();
            if (po.Credits > 0)
            {
               lblHand.Text = po.PokerHand.ToString();

               SelectPayLine(po);

               Sounds.PlaySounds(Sounds.LocalFile.PreWin);
               Thread.Sleep(100);
               this.Refresh();
            }
            else
            {
               lblHand.Text = "";
            }
            _hand.DealCount = 1;
            lblGameStatus.Text = "Hold or Draw Cards";

            btnMaxBet.Enabled = false;
            btnBetOne.Enabled = false;
         }
         else //draw cards
         {
            if (!_hold1)
            {
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               card = _deck.GetNextCard();
               this.cardImage1.CardValue = card.Value;
               _cell1 = true;
               _hand.Card1 = new Card(card.Value);
            }
            if (!_hold2)
            {
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               card = _deck.GetNextCard();
               this.cardImage2.CardValue = card.Value;
               _cell2 = true;
               _hand.Card2 = new Card(card.Value);
            }
            if (!_hold3)
            {
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               card = _deck.GetNextCard();
               this.cardImage3.CardValue = card.Value;
               _cell3 = true;
               _hand.Card3 = new Card(card.Value);
            }
            if (!_hold4)
            {
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               card = _deck.GetNextCard();
               this.cardImage4.CardValue = card.Value;
               _cell4 = true;
               _hand.Card4 = new Card(card.Value);
            }
            if (!_hold5)
            {
               Sounds.PlaySounds(Sounds.LocalFile.Deal);

               card = _deck.GetNextCard();
               this.cardImage5.CardValue = card.Value;
               _cell5 = true;
               _hand.Card5 = new Card(card.Value);
            }
            DumpCards();
            po = _hand.Evaluate();
            if (po.Credits > 0)
            {
               SelectPayLine(po);
               lblHand.Text = po.PokerHand.ToString() + " pays " + po.Credits.ToString() + " credits";

               for (int i = 1; i <= po.Credits; i++)
               {
                  _game.Credits += 1;
                  lblCredits.Text = _game.Credits.ToString();
                  Sounds.PlaySounds(Sounds.LocalFile.Winner);
                  Thread.Sleep(100);
                  this.Refresh();
               }
            }
            else
            {
               lblHand.Text = "Fun to Play Video Poker 25¢";
            }

            lblGameStatus.Text = "Game Over";
            _hand.DealCount = 0;

            lblHold1.Visible = false;
            lblHold2.Visible = false;
            lblHold3.Visible = false;
            lblHold4.Visible = false;
            lblHold5.Visible = false;

            btnMaxBet.Enabled = true;
            btnBetOne.Enabled = true;
         }
      }

      private void SelectPayLine(PayOut po)
      {
         BindingManagerBase bmb = this.BindingContext[dgPayTable.DataSource, dgPayTable.DataMember];
         int n = bmb.Count;

         if (_game.GameType == GameTypes.JacksOrBetter)
         {
            switch (po.PokerHand)
            {
               case PokerHands.RoyalFlush:
                  bmb.Position = 0;
                  break;
               case PokerHands.StraightFlush:
                  bmb.Position = 1;
                  break;
               case PokerHands.FourOfAKind:
                  bmb.Position = 2;
                  break;
               case PokerHands.FullHouse:
                  bmb.Position = 3;
                  break;
               case PokerHands.Flush:
                  bmb.Position = 4;
                  break;
               case PokerHands.Straight:
                  bmb.Position = 5;
                  break;
               case PokerHands.ThreeOfAKind:
                  bmb.Position = 6;
                  break;
               case PokerHands.TwoPair:
                  bmb.Position = 7;
                  break;
               case PokerHands.JacksOrBetter:
                  bmb.Position = 8;
                  break;
            }
         }

         if (_game.GameType == GameTypes.DoubleBonus)
         {
            switch (po.PokerHand)
            {
               case PokerHands.RoyalFlush:
                  bmb.Position = 0;
                  break;
               case PokerHands.StraightFlush:
                  bmb.Position = 1;
                  break;
               case PokerHands.FourAces:
                  bmb.Position = 2;
                  break;
               case PokerHands.FourTwoThreeOrFour:
                  bmb.Position = 3;
                  break;
               case PokerHands.FourFiveThruKing:
                  bmb.Position = 4;
                  break;
               case PokerHands.FullHouse:
                  bmb.Position = 5;
                  break;
               case PokerHands.Flush:
                  bmb.Position = 6;
                  break;
               case PokerHands.Straight:
                  bmb.Position = 7;
                  break;
               case PokerHands.ThreeOfAKind:
                  bmb.Position = 8;
                  break;
               case PokerHands.TwoPair:
                  bmb.Position = 9;
                  break;
               case PokerHands.JacksOrBetter:
                  bmb.Position = 10;
                  break;
            }
         }
      }

      private void DumpCards()
      {
         _logger.DebugFormat(String.Format("Card 1 {0} of {1}", _hand.Card1.Face.ToString(), _hand.Card1.Suit.ToString()));
         _logger.DebugFormat(String.Format("Card 2 {0} of {1}", _hand.Card2.Face.ToString(), _hand.Card2.Suit.ToString()));
         _logger.DebugFormat(String.Format("Card 3 {0} of {1}", _hand.Card3.Face.ToString(), _hand.Card3.Suit.ToString()));
         _logger.DebugFormat(String.Format("Card 4 {0} of {1}", _hand.Card4.Face.ToString(), _hand.Card4.Suit.ToString()));
         _logger.DebugFormat(String.Format("Card 5 {0} of {1}", _hand.Card5.Face.ToString(), _hand.Card5.Suit.ToString()));

      }

      private void btnHold1_Click(object sender, EventArgs e)
      {
         if (_hand.DealCount != 0)
         {
            _hold1 = !_hold1;
            lblHold1.Visible = _hold1;
         }
      }

      private void btnHold5_Click(object sender, EventArgs e)
      {
         if (_hand.DealCount != 0)
         {
            _hold5 = !_hold5;
            lblHold5.Visible = _hold5;
         }
      }

      private void btnHold3_Click(object sender, EventArgs e)
      {
         if (_hand.DealCount != 0)
         {
            _hold3 = !_hold3;
            lblHold3.Visible = _hold3;
         }

      }

      private void btnHold4_Click(object sender, EventArgs e)
      {
         if (_hand.DealCount != 0)
         {
            _hold4 = !_hold4;
            lblHold4.Visible = _hold4;
         }

      }

      private void btnHold2_Click(object sender, EventArgs e)
      {
         if (_hand.DealCount != 0)
         {
            _hold2 = !_hold2;
            lblHold2.Visible = _hold2;
         }

      }

      private void btnMaxBet_Click(object sender, EventArgs e)
      {
         _hand.CoinsPlayed = 5;
         lblWager.Text = _hand.CoinsPlayed.ToString();
      }

      private void btnBetOne_Click(object sender, EventArgs e)
      {
         if (_hand.CoinsPlayed == 5)
            _hand.CoinsPlayed = 1;
         else
            _hand.CoinsPlayed += 1;

         lblWager.Text = _hand.CoinsPlayed.ToString();
      }

      private void CardMouseClick(object sender, MouseEventArgs e)
      {
         CardImage c = (CardImage)sender;

         if (_hand.DealCount != 0)
         {
            if (c.Parent == pnlCell1)
            {
               _hold1 = !_hold1;
               lblHold1.Visible = _hold1;
            }
            if (c.Parent == pnlCell2)
            {
               _hold2 = !_hold2;
               lblHold2.Visible = _hold2;
            }
            if (c.Parent == pnlCell3)
            {
               _hold3 = !_hold3;
               lblHold3.Visible = _hold3;

            }
            if (c.Parent == pnlCell4)
            {
               _hold4 = !_hold4;
               lblHold4.Visible = _hold4;
            }
            if (c.Parent == pnlCell5)
            {
               _hold5 = !_hold5;
               lblHold5.Visible = _hold5;
            }
         }
      }

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
         _deck = null;
         _game = null;
         _hand = null;

         cardImage1.Dispose();
         cardImage2.Dispose();
         cardImage3.Dispose();
         cardImage4.Dispose();
         cardImage5.Dispose();
      }
   }
}
